// Base Kernel
function Kernel()
{
	this.width = 0;
	this.height = 0;
	this.value = new Array();
};
Kernel.staticMethod = function() {};
/*******************************************************************************************************************/

// Gaussian Kernel
function GaussianKernel()
{
	Kernel.call(this); 

	this.sigma = 1.4;
	
	this.setSigma = function(value)
	{
		sigma = Math.max(0.00000001, value);
	};

	this.kernel2D = function(size)
	{
        kernel = new Array(size);
		for (i = 0; i < size; i++) 
			kernel[i] = new Array(size);
			
		var mean = Math.floor(size/2);
		var div = (2 * Math.PI * sigma * sigma);
		var sum = 0;
		var val = 0;
		
		for (y = 0; y < size; ++y)
		{ 
			for (x = 0; x < size; ++x)	
			{
				val = Math.exp( -0.5 * (Math.pow((x-mean)/sigma, 2.0) + Math.pow((y-mean)/sigma,2.0)) ) / div;
			    kernel[y][x] = val;
			    sum += val;
			}
        }

		for (y = 0; y < size; ++y)
		{ 
			for (x = 0; x < size; ++x)	
			{
			    kernel[y][x] /= sum;
			}
        }

        return kernel;
	};
	
	
};
GaussianKernel.prototype = new Kernel();
GaussianKernel.prototype.constructor = GaussianKernel;
/*******************************************************************************************************************/

// Laplace of Gaussian (LoG) Kernel
function LoGKernel()
{
	Kernel.call(this); 

	this.sigma = 1.4;
	
	this.setSigma = function(value)
	{
		sigma = Math.max(0.00000001, value);
	};
	
	
	this.logElement = function(x, y)
	{
		var g = 0;
		var s = 0;
		var theta = this.sigma;
		
		for(ySubPixel = y - 0.5; ySubPixel < y + 0.55; ySubPixel += 0.1)
		{
			for(xSubPixel = x - 0.5; xSubPixel < x + 0.55; xSubPixel += 0.1)
			{
				s = -((xSubPixel*xSubPixel)+(ySubPixel*ySubPixel))/(2*theta*theta);
				g = g + (1/(Math.PI*Math.pow(theta,4)))*(1+s)*Math.pow(Math.E,s);
			}
		}
		g = -g/121;
		return g;
	};
	
	this.kernelValid = function(logKernel, kernelSize, theta)
	{
		var sum = 0;
		var max = logKernel[0][0];
		for(j=0;j<kernelSize;++j)
		{
			for(i=0;i<kernelSize;++i)
			{
				sum = sum+logKernel[i][j];
			}
		}

		if(sum>0.1 || sum<-0.1 || t<=0.5 || (t/kernelSize)>0.09)
		{
			// too far from a good value
			return false;
		}
		else
		{
			// adjust values slightly to get zero sum
			var delta = sum / (kernelSize * kernelSize);
			for(j=0;j<kernelSize;++j)
			{
				for(i=0;i<kernelSize;++i)
				{
					logKernel[i][j] = logKernel[i][j] - delta;
				}
			}
			return true;
		}
	};
	

	this.kernel2D = function(size)
	{
        kernel = new Array(size);
		for (i = 0; i < size; i++) 
			kernel[i] = new Array(size);
			
		var x = 0, y = 0;
		var mean = Math.floor(size/2);
		
		var sum = 0;
		var val = 0;
		var min = 1000000; 
		
		for (i = 0; i < size; ++i)
		{ 
			for (j = 0; j < size; ++j)	
			{
				x = (-mean)+j;
				y = (-mean)+i;
				kernel[i][j] = val = this.logElement(x,y);
				
				if (val > 0 && val < min)
					min = val;
			}
        }
		
		// scale kernel from 0.0000x to integer (>1), factor (/10) to make sure the positive min is nearly 0.
		var norm_factor = (1 / min) / 10;
		
		for (i = 0; i < size; ++i)
		{ 
			for (j = 0; j < size; ++j)	
			{
				kernel[i][j] *= norm_factor;
			}
        }

        return kernel;
	};
	
};
LoGKernel.prototype = new Kernel();
LoGKernel.prototype.constructor = LoGKernel;
/*******************************************************************************************************************/